package com.loveyukari.service;

import com.loveyukari.common.exception.InternalException;
import com.loveyukari.dao.RoomLiwuDao;
import com.loveyukari.dao.TmpDao;
import com.loveyukari.model.Auth;
import com.loveyukari.model.Room;
import com.loveyukari.model.RoomLiwu;
import com.loveyukari.utils.AliYunUtils;
import com.loveyukari.utils.HttpUtils;
import com.loveyukari.utils.JsonUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.lang.reflect.Array;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class RoomService {

    private Logger roomLog = LoggerFactory.getLogger("YukariRoom");
    private Logger log = LoggerFactory.getLogger(RoomService.class);

    private Map<Integer,Room> roomMap = new HashMap<Integer, Room>();
    private Map<Integer,Boolean> roomLiveMap = new HashMap<Integer, Boolean>();
    private String roomDetailApi = "http://open.douyucdn.cn/api/RoomApi/room/";
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    private Room getRoom(int roomId) throws Exception {
        String send = null;
        send = HttpUtils.sendGet(roomDetailApi+roomId);
        JSONObject roomJson = JSONObject.fromObject(send).getJSONObject("data");
        Room room = new Room();
        room.setId(roomId);
        room.setCateId(roomJson.optInt("cate_id"));
        room.setCateName(roomJson.optString("cate_name"));
        room.setRoomName(roomJson.optString("room_name"));
        room.setOwnerName(roomJson.optString("owner_name"));
        room.setRoomStatus(roomJson.optInt("room_status"));
        room.setOnline(roomJson.optInt("online"));
        room.setOwnerWeight(roomJson.optString("owner_weight"));
        room.setFansNum(roomJson.optInt("fans_num"));
        room.setStartTime(sdf.parse(roomJson.optString("start_time")));
        room.setThumb(roomJson.optString("room_thumb"));
        return room;
    }
    public Room init(int roomId){
        Room room = null;
        try {
            room = this.getRoom(roomId);
        } catch (Exception e) {
        }
        roomMap.put(roomId,room);
        return room;
    }


    @Scheduled(cron = "10 * * * * *")
    public void getRoomTask(){
        Set<Integer> set = roomMap.keySet();
        for (Integer roomId: set) {
            try {
                Room room = this.getRoom(roomId);
                if (roomId == 196 && (roomMap.get(roomId) == null || !roomMap.get(roomId).equals(room))){
                    roomLog.info(JSONObject.fromObject(room).toString());
                }
                roomMap.put(roomId,room);
            } catch (Exception e) {
                roomLog.error(e.getMessage(),e);
            }
        }
        try {
            String send = HttpUtils.sendPost("https://www.douyu.com", null);
            Document html = Jsoup.parse(send);
            Elements div = html.getElementsByClass("c-items");
            Elements lis = div.select("li");
            for (int i = 0; i < lis.size(); i++) {
                Element li = lis.get(i);
                String rid = li.attr("data-id");
                Room room = roomMap.get(Integer.valueOf(rid));
                if (room != null){
                    room.setHomePageStatus(true);
                }
            }
        } catch (Exception e) {
            roomLog.error(e.getMessage(),e);
        }
    }

    private int[] remindRoomIds = {22};
    @Scheduled(cron = "20 * * * * *")
    public void a(){
        for (int roomId : remindRoomIds){
            Room room = roomMap.get(roomId);
            if (room != null){
                if (room.getRoomStatus() == 1){
                    Boolean flag = roomLiveMap.get(roomId);
                    if (flag == null || flag){
                    } else {
                        AliYunUtils.callStartLive("18868877652",null);
                    }
                }
                roomLiveMap.put(roomId,room.getRoomStatus() == 1);
            }
        }

    }



    @PostConstruct
    public void init() {
        for (int roomId : remindRoomIds) {
            roomMap.put(roomId, null);
        }
    }





    public Room getMapRoom(Integer roomId){
        return roomMap.get(roomId);
    }


    @Autowired
    private RoomLiwuDao roomLiwuDao;
    @Autowired
    private AuthService authService;
    @Autowired
    private RedisService redisService;

    private static final String TOTAL_COUNT_KEY = "liwu:total:count:";
    private static final String USER_COUNT_KEY = "liwu:user:count:";
    private boolean countFlag = true;

    public void countLiwu(Integer gfid,Integer userId){
        if (countFlag){
            if (gfid != null){
                String totalKey = TOTAL_COUNT_KEY+gfid;
                Integer total = redisService.get(totalKey, Integer.class);
                if (total == null){
                    total = 0;
                }
                total++;
                redisService.set(totalKey,total);
                if (userId != null){
                    String userKey = USER_COUNT_KEY+userId+":"+gfid;
                    Integer userCount = redisService.get(userKey,Integer.class);
                    if (userCount == null){
                        userCount = 0;
                    }
                    userCount++;
                    redisService.set(userKey,userCount);
                }
            }
        }
    }

    public void clear(final Date giveDate){
        if (this.countFlag){
            this.countFlag = false;
            set.clear();
            final Map<String, Integer> totalMap = popMap(TOTAL_COUNT_KEY);
            final Map<String, Integer> userMap = popMap(USER_COUNT_KEY);
            new Thread(){
                @Override
                public void run() {
                    log.info(JSONObject.fromObject(totalMap).toString());
                    final int roomId = 196;
                    Set<String> keys = userMap.keySet();
                    ArrayList<RoomLiwu> roomLiwuList = new ArrayList<>();
                    for (String key :
                            keys) {
                        Integer total = userMap.get(key);
                        String[] split = key.split(":");
                        Integer userId = Integer.valueOf(split[3]);
                        Integer liwuId = Integer.valueOf(split[4]);
                        RoomLiwu roomLiwu = new RoomLiwu();
                        roomLiwu.setGiveDate(giveDate);
                        roomLiwu.setLiwuId(liwuId);
                        roomLiwu.setRoomId(roomId);
                        roomLiwu.setTotal(total);
                        roomLiwu.setUserId(userId);
                        roomLiwuList.add(roomLiwu);
                    }
                    roomLiwuDao.batchInsertRoomLiwu(roomLiwuList);
                }
            }.start();

        }
    }


    public void start(){
        this.countFlag = true;
    }

    private Set<Integer> set = new HashSet<>();
    public void start(int gfid){
        set.add(gfid);
        start();
    }
    public boolean has(int gfid){
        return set.contains(gfid);
    }

    private Map<String,Integer> popMap(String prefixKey){
        HashMap<String, Integer> map = new HashMap<>();
        Set<String> keys = redisService.keys(prefixKey+"*");
        for (String key :
                keys) {
            Integer count = redisService.get(key,Integer.class);
            map.put(key,count);
        }
        redisService.del(keys);
        return map;
    }


    public int getTotal(int gfid){
        Integer count = redisService.get(TOTAL_COUNT_KEY + gfid,Integer.class);
        if (count == null){
            count = 0;
        }
        return count;
    }

    public int getTotal(int gfid,Date date){
        int total = roomLiwuDao.sumLiwuTotal(196, gfid, date);
        return total;
    }

    @Scheduled(cron = "0 0 0 * * *")
    public void tmpStart(){
        this.clear(DateUtils.truncate(DateUtils.addDays(new Date(),-1),Calendar.DAY_OF_MONTH));
        this.start();
    }


    public List<Auth> getRoomDateLiwuHits(int roomId,Date giveDate,int liwuId,int hits){
        List<Integer> userIds = roomLiwuDao.selectUserIdByRoomLiwuDateHits(roomId, giveDate, liwuId, hits);
        List<Auth> list = new ArrayList<>();
        for (Integer userId :
                userIds) {
            Auth auth = authService.getCacheAuth(userId);
            list.add(auth);
        }
        return list;
    }
    @Autowired
    private TmpDao tmpDao;
    public List<Auth> drawRoomDateLiwuHits(int roomId,Date giveDate,int liwuId,int hits,int size,int blackId,String group) throws InternalException{
        Map<Integer, Integer> map = roomLiwuDao.selectUserIdByRoomLiwuDateHitsMap(roomId, giveDate, liwuId, hits);
        Set<Integer> authIdSet = map.keySet();
        int total = 0;
        for (Integer authId :
                authIdSet) {
            total += map.get(authId);
        }

        Random random = new Random();
        HashSet<Integer> ids = new HashSet<>();
        ArrayList<Auth> result = new ArrayList<Auth>();
        if (blackId > 0){
            Auth blackAuth = authService.getCacheAuth(blackId);
            if (blackAuth != null){
                result.add(blackAuth);
            }
        }
        Set<Integer> excludeSet = new HashSet<>();
        if (StringUtils.isNotEmpty(group)){
            excludeSet = tmpDao.selectAuthId(group);
        }
        if (size > authIdSet.size() || authIdSet.size() - excludeSet.size() < size ){
            throw new InternalException("参与抽奖人数过少");
        }
        JSONArray logInfoAuths = new JSONArray();
        while(result.size() < size){
            int count = total;
            int i = random.nextInt(total);
            for (Integer authId :
                    authIdSet) {
                count = count - map.get(authId);
                if (count <= i){
                    boolean add = ids.add(authId);
                    if(add && !excludeSet.contains(authId)){
                        Auth auth = authService.getCacheAuth(authId);
                        if (auth != null){
                            result.add(auth);
                            JSONObject logInfoAuth = new JSONObject();
                            logInfoAuth.put("index",i);
                            logInfoAuth.put("authId",authId);
                            logInfoAuth.put("authHits",map.get(authId));
                            logInfoAuths.add(logInfoAuth);
                        }
                    }
                    break;
                }
            }
        }
        if (StringUtils.isNotEmpty(group)){
            ArrayList<Integer> eids = new ArrayList<>();
            for (Auth auth :
                    result) {
                eids.add(auth.getId());
            }
            tmpDao.insertbatchDrawExclude(group,new ArrayList<Integer>(eids));
        }
        Collections.shuffle(result);
        JSONObject logInfo = new JSONObject();
        logInfo.put("roomId",roomId);
        logInfo.put("giveDate",giveDate.getTime());
        logInfo.put("gfid",liwuId);
        logInfo.put("hits",hits);
        logInfo.put("total",total);
        logInfo.put("auths",logInfoAuths);
        log.info(logInfo.toString());
        return result;
    }


}
